#include "SnakeGame.h"
/**
 * 初始化游戏 - 设置所有初始状态1
 */
void InitGame(Snake* snake) {
    // 设置随机数种子
    srand((unsigned int)time(NULL));

    // 初始化蛇结构体成员
    snake->head = NULL;
    snake->food = NULL;
    snake->direction = LEFT;
    snake->status = OK;
    snake->score = 0;
    snake->food_score = 10;
    snake->move_interval = 0.2f;
    snake->time_since_last_move = 0.0f;
    snake->speed_level = 1;

    // 初始化蛇身和食物
    InitSnake(snake);
    CreateFood(snake);
}
/**
 * 释放蛇身内存
 */
void FreeSnake(Snake* snake) {
    // 释放蛇身节点
    SnakeNode* cur = snake->head;
    while (cur != NULL) {
        SnakeNode* next = cur->next;
        free(cur);
        cur = next;
    }
    snake->head = NULL;

    // 释放食物节点
    if (snake->food != NULL) {
        free(snake->food);
        snake->food = NULL;
    }
}

/**
 * 初始化蛇身 - 创建初始长度的蛇
 */
void InitSnake(Snake* snake) {
    // 清空现有蛇身
    FreeSnake(snake);

    // 创建5个节点的初始蛇身
    for (int i = 0; i < 5; i++) {
        SnakeNode* new_node = (SnakeNode*)malloc(sizeof(SnakeNode));
        if (new_node == NULL) {
            perror("malloc\n");
            return;
        }

        // 设置节点坐标（水平排列）
        new_node->x = INIT_POS_X - i; //初始是10，-i 可以避免堆叠
        new_node->y = INIT_POS_Y;
        new_node->next = snake->head;
        snake->head = new_node;
    }
}

/**
 * 创建食物 - 在随机位置生成食物
 */
void CreateFood(Snake* snake) {
    // 释放现有食物
    if (snake->food != NULL) {
        free(snake->food);
        snake->food = NULL;
    }

    int x, y;
    int valid_position;

    // 循环直到找到有效位置
    do {
        valid_position = 1;
        // 生成随机坐标（避开边界）
        x = rand() % (GRID_WIDTH - 2) + 1;
        y = rand() % (GRID_HEIGHT - 2) + 1;

        // 检查是否与蛇身重叠
        SnakeNode* current = snake->head;
        while (current != NULL) {
            if (current->x == x && current->y == y) {
                valid_position = 0;
                break;
            }
            current = current->next;
        }
    } while (!valid_position);

    // 创建食物节点
    snake->food = (SnakeNode*)malloc(sizeof(SnakeNode));
    if (snake->food != NULL) {
        snake->food->x = x;
        snake->food->y = y;
        snake->food->next = NULL;
    }
}

// ==================== 欢迎和结束界面 ====================

/**
 * 欢迎界面
 */
void WelcomeToGame() {
    // 显示欢迎界面直到玩家按键
    while (!WindowShouldClose()) {
        DrawWelcomeScreen();
        if (IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_SPACE)) {
            break;
        }
    }
}

/**
 * 绘制欢迎界面
 */
void DrawWelcomeScreen() {
    BeginDrawing();
    ClearBackground(BACKGROUND_COLOR);

    // 使用默认字体绘制英文，如果有中文字体可以使用中文字体
    int titleWidth = MeasureText("Snake Game", 60);
    DrawText("Snake Game", SCREEN_WIDTH/2 - titleWidth/2, SCREEN_HEIGHT/2 - 80, 60, TEXT_COLOR);

    int instrWidth = MeasureText("Press SPACE or ENTER to start", 30);
    DrawText("Press SPACE or ENTER to start", SCREEN_WIDTH/2 - instrWidth/2, SCREEN_HEIGHT/2, 30, TEXT_COLOR);

    int ctrlWidth = MeasureText("Controls: WASD or Arrow Keys, R to restart, ESC to quit", 20);
    DrawText("Controls: WASD or Arrow Keys, R to restart, ESC to quit",
             SCREEN_WIDTH/2 - ctrlWidth/2, SCREEN_HEIGHT/2 + 60, 20, TEXT_COLOR);

    EndDrawing();
}

/**
 * 绘制游戏结束界面
 */
void DrawGameOverScreen(Snake* snake) {
    BeginDrawing();

    // 半透明黑色覆盖层
    DrawRectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, (Color){0, 0, 0, 180});

    // 根据结束原因显示不同消息
    const char* message;
    switch (snake->status) {
        case KILL_BY_WALL:
            message = "Hit the wall!";
            break;
        case KILL_BY_SELF:
            message = "Bite yourself!";
            break;
        case END_NORMAL:
            message = "The game is over!";
            break;
        default:
            message = "The game is over!!";
    }

    // 绘制结束消息
    int msgWidth = MeasureText(message, 50);
    DrawText(message, SCREEN_WIDTH/2 - msgWidth/2, SCREEN_HEIGHT/2 - 60, 50, WHITE);

    // 绘制分数
    char scoreText[50];
    sprintf(scoreText, "Score: %d", snake->score);
    int scoreWidth = MeasureText(scoreText, 30);
    DrawText(scoreText, SCREEN_WIDTH/2 - scoreWidth/2, SCREEN_HEIGHT/2, 30, WHITE);

    // 绘制重新开始提示
    const char* restartMsg = "renew : R";
    int restartWidth = MeasureText(restartMsg, 25);
    DrawText(restartMsg, SCREEN_WIDTH/2 - restartWidth/2, SCREEN_HEIGHT/2 + 60, 25, WHITE);

    EndDrawing();
}

// ==================== 游戏主循环 ====================

/**
 * 游戏运行主逻辑
 */
void GameRun(Snake* snake) {
    // 简洁的游戏循环
    while (!WindowShouldClose() && snake->status != END_NORMAL) {
        HandleInput(snake);

        if (snake->status == OK) {
            UpdateGame(snake);

            DrawGame(snake);
        }
        else {
            DrawGameOverScreen(snake);
        }
    }
}
/**
 * 绘制游戏画面
 */
void DrawGame(Snake* snake) {
    BeginDrawing();
    ClearBackground(BACKGROUND_COLOR);

    // 绘制边界墙
    for (int x = 0; x < GRID_WIDTH; x++) {
        DrawRectangle(x * GRID_SIZE, 0, GRID_SIZE, GRID_SIZE, WALL_COLOR);
        DrawRectangle(x * GRID_SIZE, (GRID_HEIGHT - 1) * GRID_SIZE, GRID_SIZE, GRID_SIZE, WALL_COLOR);
    }
    for (int y = 0; y < GRID_HEIGHT; y++) {
        DrawRectangle(0, y * GRID_SIZE, GRID_SIZE, GRID_SIZE, WALL_COLOR);
        DrawRectangle((GRID_WIDTH - 1) * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE, WALL_COLOR);
    }

    // 绘制食物
    if (snake->food != NULL) {
        DrawRectangle(snake->food->x * GRID_SIZE, snake->food->y * GRID_SIZE,
                     GRID_SIZE, GRID_SIZE, FOOD_COLOR);
    }

    // 绘制蛇身
    SnakeNode* current = snake->head;
    int is_head = 1;
    while (current != NULL) {
        if (is_head) {
            // 蛇头用不同颜色
            DrawRectangle(current->x * GRID_SIZE, current->y * GRID_SIZE,
                         GRID_SIZE, GRID_SIZE, SNAKE_HEAD_COLOR);
            is_head = 0;
        } else {
            // 蛇身
            DrawRectangle(current->x * GRID_SIZE, current->y * GRID_SIZE,
                         GRID_SIZE, GRID_SIZE, SNAKE_BODY_COLOR);
        }
        current = current->next;
    }

    // 绘制UI信息
    char scoreText[50];
    sprintf(scoreText, "Soure: %d", snake->score);
    DrawText(scoreText, 30, 30, 20, TEXT_COLOR);

    char speedText[50];
    sprintf(speedText, "Speed: %d", snake->speed_level);
    DrawText(speedText, 30, 50, 20, TEXT_COLOR);

    DrawText(" CONTROL : WASD keys to move    R to restart     ESC to exit",
        30, SCREEN_HEIGHT - 40, 20, TEXT_COLOR);

    EndDrawing();
}

/**
 * 更新游戏状态
 */
void UpdateGame(Snake* snake) {
    // 更新移动计时器
    snake->time_since_last_move += GetFrameTime();  //GetFrameTime()函数可以使程序不受电脑性能的影响

    // 检查是否应该移动
    //如果累计时间达到移动间隔
    if (snake->time_since_last_move >= snake->move_interval) {
        MoveSnake(snake);  //移动蛇
        snake->time_since_last_move = 0.0f;  //重新计时 为了保持蛇的移动速度
    }
}

/**
 * 处理玩家输入
 */
void HandleInput(Snake* snake) {
    // 重新开始游戏
    if (IsKeyPressed(KEY_R)) {
        ResetGame(snake);
        return;
    }

    // 退出游戏
    if (IsKeyPressed(KEY_ESCAPE)) {
        snake->status = END_NORMAL;
        return;
    }

    // 方向控制
    if ((IsKeyPressed(KEY_W) || IsKeyPressed(KEY_UP)) && snake->direction != DOWN) {
        snake->direction = UP;
    }
    else if ((IsKeyPressed(KEY_S) || IsKeyPressed(KEY_DOWN)) && snake->direction != UP) {
        snake->direction = DOWN;
    }
    else if ((IsKeyPressed(KEY_A) || IsKeyPressed(KEY_LEFT)) && snake->direction != RIGHT) {
        snake->direction = LEFT;
    }
    else if ((IsKeyPressed(KEY_D) || IsKeyPressed(KEY_RIGHT)) && snake->direction != LEFT) {
        snake->direction = RIGHT;
    }

    // 速度控制
    if (IsKeyPressed(KEY_EQUAL)) {
        // 加速
        if (snake->move_interval > 0.05f) {
            snake->move_interval -= 0.02f;
            snake->speed_level++;
            snake->food_score += 2;
        }
    }
    else if (IsKeyPressed(KEY_MINUS)) {
        // 减速
        if (snake->move_interval < 0.5f) {
            snake->move_interval += 0.02f;
            snake->speed_level--;
            if (snake->food_score > 2) {
                snake->food_score -= 2;
            }
        }
    }
}

// ==================== 游戏逻辑 ====================

/**
 * 移动蛇的逻辑。 创建新蛇头 → 检查碰撞 → 吃食物或正常移动
 */
void MoveSnake(Snake* snake) {
    // 创建新蛇头节点
    SnakeNode* new_head = (SnakeNode*)malloc(sizeof(SnakeNode));
    if (new_head == NULL) return;

    // 根据方向计算新蛇头位置
    new_head->x = snake->head->x;
    new_head->y = snake->head->y;

    switch (snake->direction) {
        case UP:    new_head->y--; break;
        case DOWN:  new_head->y++; break;
        case LEFT:  new_head->x--; break;
        case RIGHT: new_head->x++; break;
    }

    // 检查碰撞 - 使用新位置
    if (CheckCollision(snake, new_head->x, new_head->y)) {
        free(new_head);
        return;
    }

    // 检查是否吃到食物
    if (NextIsFood(new_head, snake)) {
        EatFood(new_head, snake);
    } else {
        // 正常移动：添加新头，移除尾部
        new_head->next = snake->head;
        snake->head = new_head;

        // 找到倒数第二个节点
        SnakeNode* current = snake->head;
        while (current->next->next != NULL) {
            current = current->next;
        }

        // 释放尾部节点
        free(current->next);
        current->next = NULL;
    }
}

/**
 * 检查下一个位置是否为食物
 */
int NextIsFood(SnakeNode* next_node, Snake* snake) {
    return (snake->food != NULL) &&
           (next_node->x == snake->food->x) &&
           (next_node->y == snake->food->y);
}

/**
 * 吃食物处理
 */
void EatFood(SnakeNode* next_node, Snake* snake) {
    // 将新节点作为蛇头
    next_node->next = snake->head;
    snake->head = next_node;

    // 增加分数
    snake->score += snake->food_score;

    // 创建新食物
    CreateFood(snake);
}

/**
 * 碰撞检测
 */
int CheckCollision(Snake* snake, int new_x, int new_y) {
    // 撞墙检测
    if (new_x <= 0 || new_x >= GRID_WIDTH - 1 ||
        new_y <= 0 || new_y >= GRID_HEIGHT - 1) {
        snake->status = KILL_BY_WALL;
        return 1;
    }

    // 撞自身检测
    SnakeNode* current = snake->head;
    while (current != NULL) {
        if (current->x == new_x && current->y == new_y) {
            snake->status = KILL_BY_SELF;
            return 1;
        }
        current = current->next;
    }

    return 0;
}
/**
 * 重置游戏
 */
void ResetGame(Snake* snake) {
    FreeSnake(snake);
    InitGame(snake);
}

/**
 * 游戏结束清理
 */
void GameEnd(Snake* snake) {
    FreeSnake(snake);
}